package com.example.li_han.dao;

import com.example.li_han.pojo.News;
import com.example.li_han.utils.ConnUtils;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 新闻数据访问对象类
 * 负责对news表和关联表进行数据库操作，包括增删改查等功能
 */
public class NewsDao {

    /**
     * 查询所有新闻，置顶的排在前面，按ID降序排列（支持分页）
     * @param currentPage 当前页码
     * @param pageSize 每页条数
     * @return 分页后的新闻列表
     */
    public List<News> getAllNews(int currentPage, int pageSize) {
        int start = (currentPage - 1) * pageSize;
        String sql = "SELECT n.*, nt.typeName FROM news n LEFT JOIN news_type nt ON n.typeId = nt.typeId ORDER BY n.isTop DESC, n.newsId LIMIT ?, ?";

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<News> newsList = new ArrayList<>();

        try {
            conn = ConnUtils.getConn();
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, start);
            pstmt.setInt(2, pageSize);
            rs = pstmt.executeQuery();

            while (rs.next()) {
                News news = new News();
                news.setNewsId(rs.getInt("newsId"));
                news.setTypeId(rs.getInt("typeId"));
                news.setTypeName(rs.getString("typeName"));
                news.setNewsTitle(rs.getString("newsTitle"));
                news.setNewsContent(rs.getString("newsContent"));
                news.setNewsImage(rs.getString("newsImage"));
                news.setTop(rs.getBoolean("isTop"));
                news.setShowHome(rs.getBoolean("isShowHome"));
                news.setViewCount(rs.getInt("viewCount"));
                news.setImageNews(rs.getBoolean("isImageNews"));
                newsList.add(news);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("查询所有新闻失败：" + e.getMessage());
        } finally {
            closeResources(conn, pstmt, rs);
        }
        return newsList;
    }

    /**
     * 根据新闻ID查询新闻详情
     * @param newsId 新闻ID
     * @return 新闻对象（不存在则返回null）
     */
    public News getNewsInfo(int newsId) {
        String sql = "SELECT * FROM news WHERE newsId = ?";
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        News news = null;

        try {
            conn = ConnUtils.getConn();
            pst = conn.prepareStatement(sql);
            pst.setInt(1, newsId);
            rs = pst.executeQuery();

            if (rs.next()) {
                news = new News();
                news.setNewsId(rs.getInt("newsId"));
                news.setTypeId(rs.getInt("typeId"));
                news.setNewsTitle(rs.getString("newsTitle"));
                news.setNewsContent(rs.getString("newsContent"));
                news.setNewsImage(rs.getString("newsImage"));
                news.setTop(rs.getBoolean("isTop"));
                news.setShowHome(rs.getBoolean("isShowHome"));
                news.setViewCount(rs.getInt("viewCount"));
                news.setImageNews(rs.getBoolean("isImageNews"));
                news.setPublishDate(rs.getDate("publishDate"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("查询新闻详情失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, rs);
        }
        return news;
    }

    /**
     * 根据typeName查询对应的typeId（关联news_type表）
     * @param typeName 分类名称（如“国内”）
     * @return 存在返回typeId，不存在返回-1
     */
    public int getTypeIdByTypeName(String typeName) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            conn = ConnUtils.getConn();
            String sql = "SELECT typeId FROM news_type WHERE typeName = ?";
            pst = conn.prepareStatement(sql);
            pst.setString(1, typeName);
            rs = pst.executeQuery();
            if (rs.next()) {
                return rs.getInt("typeId");
            }
            return -1;
        } catch (SQLException e) {
            throw new RuntimeException("根据typeName查询typeId失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, rs);
        }
    }

    /**
     * 添加新闻
     * @param news 新闻对象（需包含有效的typeId）
     * @return 受影响行数（1=成功，0=失败）
     */
    public int addNews(News news) {
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = ConnUtils.getConn();
            String sql = "INSERT INTO news (typeId, newsTitle, newsContent, newsImage, isTop, isShowHome, viewCount, isImageNews,publishDate) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?,?)";
            pst = conn.prepareStatement(sql);
            pst.setInt(1, news.getTypeId());
            pst.setString(2, news.getNewsTitle());
            pst.setString(3, news.getNewsContent());
            pst.setString(4, news.getNewsImage());
            pst.setBoolean(5, news.isTop());
            pst.setBoolean(6, news.isShowHome());
            pst.setInt(7, news.getViewCount());
            pst.setBoolean(8, news.isImageNews());
            pst.setDate(9, new java.sql.Date(news.getPublishDate().getTime()));
            return pst.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("添加新闻失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, null);
        }
    }

    /**
     * 更新新闻浏览量（+1）
     * @param newsId 新闻ID
     * @return true=更新成功，false=失败
     */
    public boolean updateViewCount(int newsId) {
        String sql = "UPDATE news SET viewCount = viewCount + 1 WHERE newsId = ?";
        Connection conn = null;
        PreparedStatement pst = null;

        try {
            conn = ConnUtils.getConn();
            pst = conn.prepareStatement(sql);
            pst.setInt(1, newsId);
            return pst.executeUpdate() > 0;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        } finally {
            closeResources(conn, pst, null);
        }
    }

    /**
     * 查询所有置顶新闻
     * @return 置顶新闻列表（按ID降序）
     */
    public List<News> findTopNews() {
        String sql = "SELECT n.*, nt.typeName FROM news n LEFT JOIN news_type nt ON n.typeId = nt.typeId WHERE n.isTop = 1 ORDER BY n.newsId";
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        List<News> newsList = new ArrayList<>();

        try {
            conn = ConnUtils.getConn();
            pst = conn.prepareStatement(sql);
            rs = pst.executeQuery();

            while (rs.next()) {
                News news = new News();
                news.setNewsId(rs.getInt("newsId"));
                news.setTypeId(rs.getInt("typeId"));
                news.setTypeName(rs.getString("typeName"));
                news.setNewsTitle(rs.getString("newsTitle"));
                news.setNewsContent(rs.getString("newsContent"));
                news.setNewsImage(rs.getString("newsImage"));
                news.setTop(rs.getBoolean("isTop"));
                news.setShowHome(rs.getBoolean("isShowHome"));
                news.setViewCount(rs.getInt("viewCount"));
                news.setImageNews(rs.getBoolean("isImageNews"));
                news.setPublishDate(rs.getDate("publishDate"));
                newsList.add(news);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("查询置顶新闻失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, rs);
        }
        return newsList;
    }

    /**
     * 批量删除新闻
     * @param ids 新闻ID列表
     * @return 删除成功的记录数
     */
    public int deleteBatchNews(List<Integer> ids) {
        int flag = 0;
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = ConnUtils.getConn();
            conn.setAutoCommit(false); // 开启事务

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < ids.size(); i++) {
                sb.append("?");
                if (i < ids.size() - 1) sb.append(",");
            }
            String sql = "DELETE FROM news WHERE newsId IN (" + sb + ")";
            pst = conn.prepareStatement(sql);
            for (int i = 0; i < ids.size(); i++) {
                pst.setInt(i + 1, ids.get(i));
            }
            flag = pst.executeUpdate();
            conn.commit(); // 提交事务
        } catch (SQLException e) {
            try {
                if (conn != null) conn.rollback(); // 回滚事务
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            throw new RuntimeException("批量删除新闻失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, null);
        }
        return flag;
    }

    /**
     * 根据ID删除单个新闻
     * @param newsId 新闻ID
     * @return 受影响行数
     */
    public int deleteNewsById(int newsId) {
        int result = 0;
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = ConnUtils.getConn();
            String sql = "DELETE FROM news WHERE newsId=?";
            pst = conn.prepareStatement(sql);
            pst.setInt(1, newsId);
            result = pst.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("删除单个新闻失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, null);
        }
        return result;
    }

    /**
     * 统计新闻总数量
     * @return 新闻总数
     */
    public int getTotal() {
        int total = 0;
        String sql = "SELECT count(*) FROM news";
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            conn = ConnUtils.getConn();
            pst = conn.prepareStatement(sql);
            rs = pst.executeQuery();
            if (rs.next()) {
                total = rs.getInt(1);
            }
        } catch (SQLException e) {
            throw new RuntimeException("统计新闻总数失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, rs);
        }
        return total;
    }

    /**
     * 根据新闻类型名称查询新闻
     * @param newsType 类型名称（如“国内”）
     * @return 该类型的新闻列表
     */
    public List<News> getNewsByType(String newsType) {
        List<News> newsList = new ArrayList<>();
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            conn = ConnUtils.getConn();
            String sql = "SELECT * FROM news WHERE typeId = (SELECT typeId FROM news_type WHERE typeName = ?)";
            pst = conn.prepareStatement(sql);
            pst.setString(1, newsType);
            rs = pst.executeQuery();

            while (rs.next()) {
                News news = new News();
                news.setNewsId(rs.getInt("newsId"));
                news.setTypeId(rs.getInt("typeId"));
                news.setNewsTitle(rs.getString("newsTitle"));
                news.setNewsContent(rs.getString("newsContent"));
                news.setNewsImage(rs.getString("newsImage"));
                news.setTop(rs.getBoolean("isTop"));
                news.setShowHome(rs.getBoolean("isShowHome"));
                news.setViewCount(rs.getInt("viewCount"));
                news.setImageNews(rs.getBoolean("isImageNews"));
                news.setPublishDate(rs.getDate("publishDate"));
                newsList.add(news);
            }
        } catch (SQLException e) {
            throw new RuntimeException("根据类型查询新闻失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, rs);
        }
        return newsList;
    }

    /**
     * 编辑新闻
     * @param news 新闻对象（需包含newsId）
     * @return 受影响行数
     */
    public int editNewsById(News news) {
        int result = 0;
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = ConnUtils.getConn();
            String sql = "UPDATE news SET typeId=?, newsTitle=?, newsContent=?, newsImage=?, isTop=?, isShowHome=?, viewCount=?, isImageNews=?,publishDate=? WHERE newsId=?";
            pst = conn.prepareStatement(sql);
            pst.setInt(1, news.getTypeId());
            pst.setString(2, news.getNewsTitle());
            pst.setString(3, news.getNewsContent());
            pst.setString(4, news.getNewsImage());
            pst.setBoolean(5, news.isTop());
            pst.setBoolean(6, news.isShowHome());
            pst.setInt(7, news.getViewCount());
            pst.setBoolean(8, news.isImageNews());
            if (news.getPublishDate() != null) {
                pst.setDate(9, new java.sql.Date(news.getPublishDate().getTime()));
            } else {
                // 如果为 null，设置为当前日期
                pst.setDate(9, new java.sql.Date(System.currentTimeMillis()));
            }
            pst.setInt(10, news.getNewsId());
            result = pst.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("编辑新闻失败：" + e.getMessage());
        } finally {
            closeResources(conn, pst, null);
        }
        return result;
    }

    /**
     * 关闭数据库资源
     */
    private void closeResources(Connection conn, PreparedStatement pstmt, ResultSet rs) {
        try {
            if (rs != null) rs.close();
            if (pstmt != null) pstmt.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}